
package com.rt.schedulenew.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.rt.schedulebase.dto.*;
import com.rt.schedulebase.entity.*;
import com.rt.schedulebase.mapper.ExamApplyMapper;
import com.rt.schedulebase.mapper.ExamScheduleMapper;
import com.rt.schedulenew.api.*;
import com.rt.schedulebase.dto.ConfigDto;
import com.rt.schedulenew.utils.base.BigDecimalUtil;
import com.rt.schedulenew.utils.base.CommonUtil;
import com.rt.schedulenew.utils.base.ConstantsUtil;
import com.rt.schedulenew.utils.global.BusinessException;
import com.rt.schedulenew.utils.global.JsonResult;
import com.rt.schedulenew.utils.util.DateUtil;
import com.rt.schedulenew.utils.util.HttpUtil;
import com.rt.schedulenew.utils.util.JsonUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.ResourceAccessException;

import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class ConfigServiceImpl implements IConfigService {
    private Logger logger = LoggerFactory.getLogger(ConfigServiceImpl.class);
    @Autowired
    private CacheServiceImpl cacheServiceImpl;
    @Autowired
    private ExamApplyItemServiceImpl examApplyItemServiceImpl;
    @Autowired
    private IExamClinicSynLogService examClinicSynLogService;
    @Autowired
    private ExamScheduleMapper examScheduleMapper;
    @Autowired
    private DictScheduleApmServiceImpl dictScheduleApmServiceImpl;
    @Autowired
    private ExamApplyMapper examApplyMapper;
    @Autowired
    private IExamApplyService examApplyService;
    @Autowired
    private IExamApplyPatientIdService examApplyPatientIdService;
    @Autowired
    private ICommonService commonService;
    @Autowired
    private IDictUsersService dictUsersService;

    @Override
    public String getConfigByName(String paramName) {
        String paramValue = cacheServiceImpl.getConfigByName(paramName);
        return paramValue;
    }

    public List<String> getConfigListByName(String paramName) {
        String paramValue = cacheServiceImpl.getConfigByName(paramName);
        return CommonUtil.split2List(paramValue);
    }

    public List<String> getNotExamClassList() {
        String notExamClass = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.NOT_EXAM_CLASS.getKey());
        List<String> list = new ArrayList<>();
        if (StringUtils.isNotBlank(notExamClass)) {
            list = CommonUtil.split2List(notExamClass);
        }
        return list;
    }

    /**
     * 【按项目预约量系数占号的检查类别】
     *
     * @return
     */
    @Override
    public List<String> getOrganExamClassList() {
        String organExamClass = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.ORGAN_EXAM_CLASS.getKey());
        List<String> list = new ArrayList<>();
        if (StringUtils.isNotBlank(organExamClass)) {
            list = CommonUtil.split2List(organExamClass);
        }
        return list;
    }

    /***
     * 获取 【传入的ic卡号加前缀】cardPre：表示卡号前缀，length：表示长度是几位的IcCard值需要加前缀，为空表示不受长度限制，多个长度用英文逗号“,”分隔
     * @param icCard
     * @return
     */
    public String getIcCardPre(String icCard) {
        if (StringUtils.isNotBlank(icCard)) {
            String icCardPresStr = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.IC_CARD_PRES.getKey());
            if (StringUtils.isNotBlank(icCardPresStr)) {
                List<ConfigDto.IcCardPreScope> icCardPreScopeList = JsonUtil.toList(icCardPresStr, ConfigDto.IcCardPreScope.class);
                if (icCardPreScopeList != null && icCardPreScopeList.size() > 0) {
                    Map<String, String> map = new HashMap<>();
                    for (ConfigDto.IcCardPreScope icCardPreScope : icCardPreScopeList) {
                        String cardPre = icCardPreScope.getCardPre();
                        String length = icCardPreScope.getLength();
                        if (StringUtils.isNotBlank(length)) {
                            map.put(length, cardPre);
                        }
                    }
                    String len = String.valueOf(icCard.length());
                    String prefix = map.get(len);
                    if (StringUtils.isNotBlank(prefix)) {
                        return prefix + icCard;
                    }
                    return icCard;
                }
            }
            return icCard;
        }
        return null;
    }

    /***
     *  【卡号栏查询支持类型】ic_card(诊疗卡号),inpatient_no(住院号),outpatient_no(门诊号),apply_no(申请单号),identity_card(身份证号),mi_card(医保卡号),sick_id(病人标识号),health_card(健康卡号),out_reg_no(挂号号),case_no(病案编号)
     * @return
     */
    public String getIcCardInputSupport() {
        String icCardInputSupport = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.IC_CARD_INPUT_SUPPORT.getKey());
        if (StringUtils.isNotBlank(icCardInputSupport)) {
            return icCardInputSupport;
        }
        return "ic_card,inpatient_no,outpatient_no,identity_card,mi_card,sick_id,health_card,out_reg_no,case_no";
    }

    /***
     *  【是否启用综合号码新查询支持类型】(1：关闭   0：启用)，domainId：表示支持的卡号类型，
     *  值ID参数意思可参考EXAM_APPLY_PATIENT_ID表的[DOMAIN_ID]字段的定义，为空的时候则查询所有值ID
     * @return
     */
    public List<String> getIcCardInputNewSupport() {
        List<String> domainIdList = new ArrayList<String>();
        String isIcCardInputNewSupport = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.IS_IC_CARD_INPUT_NEW_SUPPORT.getKey());
        if (StringUtils.isNotBlank(isIcCardInputNewSupport)) {
            ConfigDto.IcCardInputNewSupport icCardInputNewSupport = JsonUtil.toBean(isIcCardInputNewSupport, ConfigDto.IcCardInputNewSupport.class);
            if (icCardInputNewSupport != null && "0".equals(icCardInputNewSupport.getGrant())) {
                if (!icCardInputNewSupport.getDomainId().isEmpty()) {
                    domainIdList = icCardInputNewSupport.getDomainId();
                } else {
                    String domainIdStr = "0001,0002,0003,0004,0005,0006,0007,0008,0009,0010,0011,0012,0013,0014,0015,0016,0017,0018";
                    domainIdList = CommonUtil.split2List(domainIdStr);
                }
            }
        }
        return domainIdList;
    }

    /**
     * 获取 运送工具类型
     *
     * @return
     */
    public List<String> getTransTools() {
        List<String> transToolList = new ArrayList<String>();
        String transTool = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.TRANS_TOOL.getKey());
        if (StringUtils.isNotBlank(transTool)) {
            transToolList = CommonUtil.split2List(transTool);
        } else {
            transToolList.add("平床");
            transToolList.add("轮椅");
            transToolList.add("步行");
        }
        return transToolList;
    }

    public boolean isOpenConfig(String paramName) {
        boolean flag = false;
        if (StringUtils.isNotBlank(paramName)) {
            String configValue = cacheServiceImpl.getConfigByName(paramName);
            if (StringUtils.isNotBlank(configValue) && "0".equals(configValue)) {
                flag = true;
            }
        }
        return flag;
    }

    public List<String> getSmsNoticePatientSourceList() {
        List<String> patientSourceList = new ArrayList<String>();
        String smsNoticePatientSource = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.SMS_NOTICE_PATIENT_SOURCE.getKey());
        if (StringUtils.isNotBlank(smsNoticePatientSource)) {
            patientSourceList = CommonUtil.split2List(smsNoticePatientSource);
        }
        return patientSourceList;
    }

    public List<DictExamQueue> getSmsNoticeQueueList() {
        List<DictExamQueue> queueList = new ArrayList<>();
        String smsNoticeQueue = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.SMS_NOTICE_QUEUE.getKey());
        if (StringUtils.isNotBlank(smsNoticeQueue)) {
            queueList = JsonUtil.toList(smsNoticeQueue, DictExamQueue.class);
        }
        return queueList;
    }

    public List<DictExamItem> getNeedConfirmItemList() {
        List<DictExamItem> itemDtoList = new ArrayList<DictExamItem>();
        String needConfirmItem = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.NEED_CONFIRM_ITEM.getKey());
        if (StringUtils.isNotBlank(needConfirmItem)) {
            itemDtoList = JsonUtil.toList(needConfirmItem, DictExamItem.class);
        }
        return itemDtoList;
    }

    public String getPatientSourceIn() {
        String patientSourceIn = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.PATIENT_SOURCE_IN.getKey());
        if (StringUtils.isNotBlank(patientSourceIn)) {
            return patientSourceIn;
        }
        return "住院";
    }

    /**
     * 预约之后是否自动打印凭条
     *
     * @param ea
     * @return
     */
    public boolean isPrint4Schedule(ExamApplyDto ea) {
        boolean isPrint = false;
        List<ConfigDto.PrintTicketAfterSchedule> printTicketAfterScheduleList = JsonUtil.toList(getConfigByName(ConstantsUtil.ConfigName.PRINT_TICKET_AFTER_SCHEDULE.getKey()), ConfigDto.PrintTicketAfterSchedule.class);
        if (printTicketAfterScheduleList != null && !printTicketAfterScheduleList.isEmpty()) {
            for (ConfigDto.PrintTicketAfterSchedule ticketAfterSchedule : printTicketAfterScheduleList) {
                if (ticketAfterSchedule.getPrintTicketTerminalType().equals(ea.getTerminalType())) {
                    if (ticketAfterSchedule.getPrintTicketExamClass() != null && !ticketAfterSchedule.getPrintTicketExamClass().isEmpty() && ticketAfterSchedule.getPrintTicketPatientSource() != null && !ticketAfterSchedule.getPrintTicketPatientSource().isEmpty()) {
                        if (ticketAfterSchedule.getPrintTicketExamClass().contains(ea.getExamClass()) && ticketAfterSchedule.getPrintTicketPatientSource().contains(ea.getPatientSource())) {
                            isPrint = true;
                            break;
                        }
                    } else if (ticketAfterSchedule.getPrintTicketExamClass() != null && !ticketAfterSchedule.getPrintTicketExamClass().isEmpty()) {
                        if (ticketAfterSchedule.getPrintTicketExamClass().contains(ea.getExamClass())) {
                            isPrint = true;
                            break;
                        }
                    } else if (ticketAfterSchedule.getPrintTicketPatientSource() != null && !ticketAfterSchedule.getPrintTicketPatientSource().isEmpty()) {
                        if (ticketAfterSchedule.getPrintTicketPatientSource().contains(ea.getPatientSource())) {
                            isPrint = true;
                            break;
                        }
                    } else {
                        if ((ticketAfterSchedule.getPrintTicketExamClass() == null || ticketAfterSchedule.getPrintTicketExamClass().isEmpty()) && (ticketAfterSchedule.getPrintTicketPatientSource() == null || ticketAfterSchedule.getPrintTicketPatientSource().isEmpty())) {
                            isPrint = true;
                            break;
                        }
                    }
                }
            }
        }
        return isPrint;
    }

    public boolean isPrintCode4Schedule(ExamApplyDto ea) {
        boolean isPrint = false;
        List<ExamApplyItemDto> examApplyItemDtoList = ea.getItems();
        List<DictExamItem> autoPrintNumByItemList = JsonUtil.toList(getConfigByName(ConstantsUtil.ConfigName.AUTO_PRINT_NUM_BY_ITEM.getKey()), DictExamItem.class);
        if (autoPrintNumByItemList != null && !autoPrintNumByItemList.isEmpty() && examApplyItemDtoList != null && !examApplyItemDtoList.isEmpty()) {
            for (ExamApplyItemDto applyItemDto : examApplyItemDtoList) {
                String examClass = applyItemDto.getExamClass();
                String itemCode = applyItemDto.getItemCode();
                String itemName = applyItemDto.getItemName();
                for (DictExamItem autoPrintNumByItem : autoPrintNumByItemList) {
                    String autoPrintExamClass = autoPrintNumByItem.getExamClass();
                    String autoPrintItemCode = autoPrintNumByItem.getItemCode();
                    String autoPrintItemName = autoPrintNumByItem.getItemName();
                    if (StringUtils.isBlank(autoPrintItemCode) && StringUtils.isBlank(autoPrintItemName)
                            && StringUtils.isNotBlank(autoPrintExamClass) && autoPrintExamClass.equals(examClass)) {
                        isPrint = true;
                        break;
                    }
                    if (StringUtils.isNotBlank(autoPrintExamClass) && autoPrintExamClass.equals(examClass)
                            && ((StringUtils.isNotBlank(autoPrintItemCode) && autoPrintItemCode.equals(itemCode))
                            || (StringUtils.isNotBlank(autoPrintItemName) && autoPrintItemName.equals(itemName)))) {
                        isPrint = true;
                        break;
                    }
                }
            }
        }
        return isPrint;
    }

    /***
     * 报道后是否打印凭条
     * @param ea
     * @return
     */
    public boolean isPrint4Sign(ExamApplyDto ea) {
        boolean isPrint = false;
        List<ConfigDto.PrintTicketAfterSign> printTicketAfterSignList = JsonUtil.toList(getConfigByName(ConstantsUtil.ConfigName.PRINT_TICKET_AFTER_SIGN.getKey()), ConfigDto.PrintTicketAfterSign.class);
        if (printTicketAfterSignList != null && !printTicketAfterSignList.isEmpty()) {
            for (ConfigDto.PrintTicketAfterSign ticketAfterSign : printTicketAfterSignList) {
                if (ticketAfterSign.getPrintTicketTerminalType().equals(ea.getTerminalType())) {
                    if (ticketAfterSign.getPrintTicketExamClass() != null
                            && !ticketAfterSign.getPrintTicketExamClass().isEmpty()
                            && ticketAfterSign.getPrintTicketPatientSource() != null
                            && !ticketAfterSign.getPrintTicketPatientSource().isEmpty()) {
                        if (ticketAfterSign.getPrintTicketExamClass().contains(ea.getExamClass())
                                && ticketAfterSign.getPrintTicketPatientSource().contains(ea.getPatientSource())) {
                            isPrint = true;
                            break;
                        }
                    } else if (ticketAfterSign.getPrintTicketExamClass() != null && !ticketAfterSign.getPrintTicketExamClass().isEmpty()) {
                        if (ticketAfterSign.getPrintTicketExamClass().contains(ea.getExamClass())) {
                            isPrint = true;
                            break;
                        }
                    } else if (ticketAfterSign.getPrintTicketPatientSource() != null && !ticketAfterSign.getPrintTicketPatientSource().isEmpty()) {
                        if (ticketAfterSign.getPrintTicketPatientSource().contains(ea.getPatientSource())) {
                            isPrint = true;
                            break;
                        }
                    } else {
                        if ((ticketAfterSign.getPrintTicketExamClass() == null || ticketAfterSign.getPrintTicketExamClass().isEmpty())
                                && (ticketAfterSign.getPrintTicketPatientSource() == null || ticketAfterSign.getPrintTicketPatientSource().isEmpty())) {
                            isPrint = true;
                            break;
                        }
                    }
                }
            }
        }
        return isPrint;
    }

    /***
     * 是否当日签到
     * true 预约后调用签到接口 false 不调用签到接口
     * @param examApplyDto
     * @param apm
     * @return
     */
    public boolean isScheduleTodayBySign(ExamApplyDto examApplyDto, DictScheduleApmDto apm) {
        // 预约时段
        String scheduleApm = examApplyDto.getScheduleApm();
        if (StringUtils.isNotBlank(apm.getTimeStart()) && StringUtils.isNotBlank(apm.getTimeEnd())) {
            String timeStart = apm.getTimeStart().substring(0, apm.getTimeStart().lastIndexOf(":"));
            String timeEnd = DateUtil.date2Str(DateUtil.minAdd("2022-01-01 " + apm.getTimeEnd().substring(0, apm.getTimeEnd().lastIndexOf(":")), 1), DateUtil.FORMAT_HHMM);
            scheduleApm = timeStart + "~" + timeEnd;
        }
        // 日期
        String scheduleDate = examApplyDto.getScheduleDate();
        // 状态
        String scheduleStatus = examApplyDto.getScheduleStatus();
        // 最早
        String timeEarliest = apm.getNewTimeEarliest();
        if (StringUtils.isNotBlank(timeEarliest) && timeEarliest.split(":").length == 2) {
            timeEarliest += ":00";
        }
        String timeSignin = apm.getNewTimeSignin();
        if (StringUtils.isNotBlank(timeSignin) && timeSignin.split(":").length == 2) {
            timeSignin += ":00";
        }
        boolean isToday = false;
        try {
            String curDate = DateUtil.getCurrDateStr();
            long nowTime = DateUtil.getNow().getTime();
            String examClass = examApplyDto.getExamClass();
            // 不可以报到的类别
            List<String> noClickSignBtnByExamClassList = getConfigListByName(ConstantsUtil.ConfigName.NO_CLICK_SIGN_BTN_BY_EXAM_CLASS.getKey());
            ConfigDto.ScheduleTodayBySign scheduleTodayBySign = JsonUtil.toBean(getConfigByName(ConstantsUtil.ConfigName.IS_SCHEDULE_TODAY_BY_SIGN.getKey()), ConfigDto.ScheduleTodayBySign.class);
            if (scheduleTodayBySign != null
                    && "0".equals(scheduleTodayBySign.getGrant()) && !noClickSignBtnByExamClassList.contains(examClass)
                    && curDate.equals(scheduleDate) && !"3".equals(scheduleStatus) && !"5".equals(scheduleStatus)) {
                String[] apmArr = scheduleApm.split("~");
                long startTime = 0L;
                long endTime = 0L;
                if (StringUtils.isNotBlank(timeEarliest)) {
                    if ("0".equals(scheduleTodayBySign.getIsScheduleApmTodayBySign())) {
                        if (StringUtils.isNotBlank(timeSignin)) {
                            startTime = DateUtil.parse(curDate + " " + timeEarliest, DateUtil.FORMAT_DATETIME).getTime();
                            endTime = DateUtil.parse(curDate + " " + timeSignin, DateUtil.FORMAT_DATETIME).getTime();
                            if (nowTime >= startTime && nowTime <= endTime) {
                                isToday = true;
                            }
                        } else {
                            startTime = DateUtil.parse(curDate + " " + timeEarliest, DateUtil.FORMAT_DATETIME).getTime();
                            endTime = DateUtil.parse(curDate + " " + apmArr[1] + ":00", DateUtil.FORMAT_DATETIME).getTime();
                            if (nowTime >= startTime && nowTime <= endTime) {
                                isToday = true;
                            }
                        }
                    } else {
                        long tippingPoint = DateUtil.parse(curDate + " " + timeEarliest, DateUtil.FORMAT_DATETIME).getTime();
                        if (nowTime >= tippingPoint) {
                            isToday = true;
                        }
                    }
                } else if ("0".equals(scheduleTodayBySign.getIsScheduleApmTodayBySign())) {
                    if (StringUtils.isNotBlank(timeSignin)) {
                        startTime = DateUtil.parse(curDate + " " + apmArr[0] + ":00", DateUtil.FORMAT_DATETIME).getTime();
                        endTime = DateUtil.parse(curDate + " " + timeSignin, DateUtil.FORMAT_DATETIME).getTime();
                        if (nowTime >= startTime && nowTime <= endTime) {
                            isToday = true;
                        }
                    } else {
                        startTime = DateUtil.parse(curDate + " " + apmArr[0] + ":00", DateUtil.FORMAT_DATETIME).getTime();
                        endTime = DateUtil.parse(curDate + " " + apmArr[1] + ":00", DateUtil.FORMAT_DATETIME).getTime();
                        if (nowTime >= startTime && nowTime <= endTime) {
                            isToday = true;
                        }
                    }
                } else {
                    isToday = true;
                }
            }
            return isToday;
        } catch (Exception e) {
            return false;
        }
    }

    /***
     * 判断终端的申请时间限制
     * 如果超过限制就不展示申请单
     * @param terminalType
     * @param examClass
     * @param reqDate
     * @return
     */
    public boolean isApplyDateLimit(String terminalType, String examClass, String reqDate) {
        boolean bool = false;
        List<ConfigDto.SelfReqDateLimit> list = JsonUtil.toList(getConfigByName(ConstantsUtil.ConfigName.SELF_REQ_DATE_LIMIT.getKey()), ConfigDto.SelfReqDateLimit.class);
        if (list != null && !list.isEmpty()) {
            for (ConfigDto.SelfReqDateLimit selfReqDateLimit : list) {
                if (selfReqDateLimit.getExamClass() != null && selfReqDateLimit.getExamClass().contains(examClass) && (selfReqDateLimit.getTerminalType().isEmpty() || selfReqDateLimit.getTerminalType().contains(terminalType))) {
                    int d = (selfReqDateLimit.getExpireDay() != null) ? selfReqDateLimit.getExpireDay() : 0;
                    String limitDate = DateUtil.date2Str(DateUtil.dateAdd(DateUtil.getNow(), -d), DateUtil.FORMAT_DATE);
                    if (reqDate.compareTo(limitDate) < 0) {
                        bool = true;
                        break;
                    }
                }
            }
        }
        return bool;
    }

    /**
     * 获取自动执行任务列表配置
     *
     * @return
     */
    public List<ConfigDto.SysTask> getTaskList() {
        String isSysTaskStr = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.IS_SYS_TASK.getKey());
        cacheServiceImpl.clearConfigCache(ConstantsUtil.ConfigName.IS_SYS_TASK.getKey());

        List<ConfigDto.SysTask> lsTask = new ArrayList<>();
        if (StringUtils.isNotBlank(isSysTaskStr)) {
            List<ConfigDto.SysTask> list = JsonUtil.toList(isSysTaskStr, ConfigDto.SysTask.class);
            for (ConfigDto.SysTask sysTask : list) {
                if ("0".equals(sysTask.getState())) {
                    lsTask.add(sysTask);
                }
            }
        }
        // 自动预约
        String isAutoTask = getConfigByName(ConstantsUtil.ConfigName.IS_AUTO_SCHEDULE_BY_TIMING_TASK.getKey());
        if ("0".equals(isAutoTask)) {
            String autoTaskStr = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.AUTO_SCHEDULE_BY_TIMING_TASK.getKey());
            if (StringUtils.isNotBlank(autoTaskStr)) {
                List<ConfigDto.CommonSet> list = JsonUtil.toList(autoTaskStr, ConfigDto.CommonSet.class);
                for (ConfigDto.CommonSet commonSet : list) {
                    ConfigDto.SysTask sysTask = new ConfigDto.SysTask();
                    sysTask.setMethodName("autoScheduleTask");
                    String cron = "* " + commonSet.getLimitTime().split(":")[1] + " " + commonSet.getLimitTime().split(":")[0] + " * * ?";
                    sysTask.setCron(cron);
                    sysTask.setState("0");
                    lsTask.add(sysTask);
                }
            }
        }
        return lsTask;
    }

    public ConfigDto.SysTask getTaskInfoByMethodName(String methodName) {
        List<ConfigDto.SysTask> list = getTaskList();
        for (ConfigDto.SysTask sysTask : list) {
            if ("0".equals(sysTask.getState()) && sysTask.getMethodName().equals(methodName)) {
                return sysTask;
            }
        }
        return null;
    }

    public String isItemBefore(ExamApplyDto ea, ExamScheduleDto es) {
        boolean bool = false;
        String desc = null;
        int beforeDaysMax = 0;
        int afterDaysMax = 0;
        int beforeHoursMax = 0;
        int afterHoursMax = 0;
        List<ConfigDto.ItemBefore> list = JsonUtil.toList(getConfigByName(ConstantsUtil.ConfigName.ITEM_BEFORE.getKey()), ConfigDto.ItemBefore.class);
        if (list != null && list.size() > 0) {
            for (ConfigDto.ItemBefore itemBefore : list) {
                int beforeDays = (itemBefore.getBeforeDays() != null) ? itemBefore.getBeforeDays() : 0;
                int afterDays = (itemBefore.getAfterDays() != null) ? itemBefore.getAfterDays() : 0;
                int beforeHours = (itemBefore.getBeforeHours() != null) ? itemBefore.getBeforeHours() : 0;
                int afterHours = (itemBefore.getAfterHours() != null) ? itemBefore.getAfterHours() : 0;
                if (beforeDays > beforeDaysMax) {
                    beforeDaysMax = beforeDays;
                }
                if (afterDays > afterDaysMax) {
                    afterDaysMax = afterDays;
                }
                if (beforeHours > beforeHoursMax) {
                    beforeHoursMax = beforeHours;
                }
                if (afterHours > afterHoursMax) {
                    afterHoursMax = afterHours;
                }
            }
            int max = 0;
            if (beforeDaysMax > max) {
                max = beforeDaysMax;
            }
            if (afterDaysMax > max) {
                max = afterDaysMax;
            }
            if (beforeHoursMax > afterHoursMax) {
                max += beforeHoursMax / 24;
            } else {
                max += afterHoursMax / 24;
            }
            String startDate = DateUtil.date2Str(DateUtil.dateAdd(es.getScheduledDate(), -max), DateUtil.FORMAT_DATE);
            String endDate = DateUtil.date2Str(DateUtil.dateAdd(es.getScheduledDate(), max), DateUtil.FORMAT_DATE);
            ExamApplyDto e = new ExamApplyDto();
            e.setStartDate(startDate);
            e.setEndDate(endDate);
            e.setSickId(ea.getSickId());
            List<ExamApplyItemDto> otherItems = examApplyItemServiceImpl.selectOtherSchedule(e);
            List<String> mergeNos = CommonUtil.split2List(ea.getMergeNo());
            Iterator<ExamApplyItemDto> it = otherItems.iterator();
            while (it.hasNext()) {
                ExamApplyItemDto item = it.next();
                String mergeNo = item.getMergeNo();
                if (mergeNos.contains(mergeNo)) {
                    it.remove();
                }
            }
            if (otherItems.size() > 0) {
                for (ConfigDto.ItemBefore itemBefore2 : list) {
                    bool = false;
                    List<String> itemCodeA = new ArrayList<String>();
                    List<DictExamItem> examItemA = itemBefore2.getExamItemA();
                    if (examItemA != null) {
                        for (DictExamItem dei : examItemA) {
                            itemCodeA.add(dei.getExamClass() + "=" + dei.getItemCode());
                        }
                    }
                    List<String> itemCodeB = new ArrayList<String>();
                    List<DictExamItem> examItemB = itemBefore2.getExamItemB();
                    if (examItemB != null) {
                        for (DictExamItem dei2 : examItemB) {
                            itemCodeB.add(dei2.getExamClass() + "=" + dei2.getItemCode());
                        }
                    }
                    for (ExamApplyItemDto item2 : ea.getItems()) {
                        String itemCode = item2.getExamClass() + "=" + item2.getItemCode();
                        String itemCodeBlank = item2.getExamClass() + "=空";
                        if (itemCodeA.contains(itemCode) || itemCodeA.contains(itemCodeBlank)) {
                            bool = true;
                            break;
                        }
                    }
                    if (bool) {
                        for (ExamApplyItemDto item2 : otherItems) {
                            String itemCode = item2.getExamClass() + "=" + item2.getItemCode();
                            String itemCodeBlank = item2.getExamClass() + "=空";
                            if (itemCodeB.contains(itemCode) || itemCodeB.contains(itemCodeBlank)) {
                                int days = DateUtil.getIntervalDays(es.getScheduledDate(), item2.getScheduleDate());
                                String scheTime = es.getScheduledDate() + " " + es.getTimeStart();
                                String otherTime = item2.getScheduleDate() + " " + item2.getTimeStart();
                                String otherApm = item2.getScheduleDate() + " " + item2.getScheduleApm();
                                int hours = DateUtil.getIntervalHours(scheTime, otherTime);
                                if (scheTime.compareTo(otherTime) <= 0 && itemBefore2.getBeforeHours() != null && hours < itemBefore2.getBeforeHours()) {
                                    desc = "当前项目与" + item2.getItemName() + "项目【" + otherApm + "】要求间隔" + itemBefore2.getBeforeHours() + "小时，请重新选择预约时间，如有疑问，请到护士站咨询。";
                                } else if (scheTime.compareTo(otherTime) >= 0 && itemBefore2.getAfterHours() != null && hours < itemBefore2.getAfterHours()) {
                                    desc = "当前项目与" + item2.getItemName() + "项目【" + otherApm + "】要求间隔" + itemBefore2.getAfterHours() + "小时，请重新选择预约时间，如有疑问，请到护士站咨询。";
                                } else if (es.getScheduledDate().compareTo(item2.getScheduleDate()) <= 0 && itemBefore2.getBeforeDays() != null && days < itemBefore2.getBeforeDays()) {
                                    String str = "";
                                    if (itemBefore2.getAfterDays() != null) {
                                        String afterDate = DateUtil.date2Str(DateUtil.dateAdd(item2.getScheduleDate(), itemBefore2.getAfterDays() - 1), DateUtil.FORMAT_DATE);
                                        str = ((itemBefore2.getAfterDays() != null) ? ("或者" + afterDate + "以后") : "");
                                    }
                                    String beforeDate = DateUtil.date2Str(DateUtil.dateAdd(item2.getScheduleDate(), -itemBefore2.getBeforeDays() + 1), DateUtil.FORMAT_DATE);
                                    desc = "当前项目与" + item2.getItemName() + "项目检查时间要求间隔" + itemBefore2.getBeforeDays() + "天，只能预约" + beforeDate + "以前" + str + "的日期，如有疑问，请到护士站咨询。";
                                } else if (es.getScheduledDate().compareTo(item2.getScheduleDate()) >= 0 && itemBefore2.getAfterDays() != null && days < itemBefore2.getAfterDays()) {
                                    String str = "";
                                    if (itemBefore2.getBeforeDays() != null) {
                                        String beforeDate = DateUtil.date2Str(DateUtil.dateAdd(item2.getScheduleDate(), -itemBefore2.getBeforeDays() + 1), DateUtil.FORMAT_DATE);
                                        str = ((itemBefore2.getBeforeDays() != null) ? ("或者" + beforeDate + "以前") : "");
                                    }
                                    String afterDate = DateUtil.date2Str(DateUtil.dateAdd(item2.getScheduleDate(), itemBefore2.getAfterDays() - 1), DateUtil.FORMAT_DATE);
                                    desc = "当前项目与" + item2.getItemName() + "项目检查时间要求间隔" + itemBefore2.getAfterDays() + "天，只能预约" + afterDate + "以后" + str + "的日期，如有疑问，请到护士站咨询。";
                                }
                                if (desc != null) {
                                    return desc;
                                }
                            }
                        }
                    } else {
                        for (ExamApplyItemDto item2 : ea.getItems()) {
                            String itemCode = item2.getExamClass() + "=" + item2.getItemCode();
                            String itemCodeBlank = item2.getExamClass() + "=空";
                            if (itemCodeB.contains(itemCode) || itemCodeB.contains(itemCodeBlank)) {
                                bool = true;
                                break;
                            }
                        }
                        if (!bool) {
                            continue;
                        }
                        for (ExamApplyItemDto item2 : otherItems) {
                            String itemCode = item2.getExamClass() + "=" + item2.getItemCode();
                            String itemCodeBlank = item2.getExamClass() + "=空";
                            if (itemCodeA.contains(itemCode) || itemCodeA.contains(itemCodeBlank)) {
                                int days = DateUtil.getIntervalDays(es.getScheduledDate(), item2.getScheduleDate());
                                String scheTime = es.getScheduledDate() + " " + es.getTimeStart();
                                String otherTime = item2.getScheduleDate() + " " + item2.getTimeStart();
                                String otherApm = item2.getScheduleDate() + " " + item2.getScheduleApm();
                                int hours = DateUtil.getIntervalHours(scheTime, otherTime);
                                if (otherTime.compareTo(scheTime) <= 0 && itemBefore2.getBeforeHours() != null && hours < itemBefore2.getBeforeHours()) {
                                    desc = "当前项目与" + item2.getItemName() + "项目【" + otherApm + "】要求间隔" + itemBefore2.getBeforeHours() + "小时，请重新选择预约时间，如有疑问，请到护士站咨询。";
                                } else if (otherTime.compareTo(scheTime) >= 0 && itemBefore2.getAfterHours() != null && hours < itemBefore2.getAfterHours()) {
                                    desc = "当前项目与" + item2.getItemName() + "项目【" + otherApm + "】要求间隔" + itemBefore2.getAfterHours() + "小时，请重新选择预约时间，如有疑问，请到护士站咨询。";
                                } else if (item2.getScheduleDate().compareTo(es.getScheduledDate()) <= 0 && itemBefore2.getBeforeDays() != null && days < itemBefore2.getBeforeDays()) {
                                    String str = "";
                                    if (itemBefore2.getAfterDays() != null) {
                                        String afterDate = DateUtil.date2Str(DateUtil.dateAdd(item2.getScheduleDate(), -itemBefore2.getAfterDays() + 1), DateUtil.FORMAT_DATE);
                                        str = ((itemBefore2.getAfterDays() != null) ? ("或者" + afterDate + "以前") : "");
                                    }
                                    String beforeDate = DateUtil.date2Str(DateUtil.dateAdd(item2.getScheduleDate(), itemBefore2.getBeforeDays() - 1), DateUtil.FORMAT_DATE);
                                    desc = "当前项目与" + item2.getItemName() + "项目检查时间要求间隔" + itemBefore2.getBeforeDays() + "天，只能预约" + beforeDate + "以后" + str + "的日期，如有疑问，请到护士站咨询。";
                                } else if (item2.getScheduleDate().compareTo(es.getScheduledDate()) >= 0 && itemBefore2.getAfterDays() != null && days < itemBefore2.getAfterDays()) {
                                    String str = "";
                                    if (itemBefore2.getBeforeDays() != null) {
                                        String beforeDate = DateUtil.date2Str(DateUtil.dateAdd(item2.getScheduleDate(), itemBefore2.getBeforeDays() - 1), DateUtil.FORMAT_DATE);
                                        str = ((itemBefore2.getBeforeDays() != null) ? ("或者" + beforeDate + "以前") : "");
                                    }
                                    String afterDate = DateUtil.date2Str(DateUtil.dateAdd(item2.getScheduleDate(), -itemBefore2.getAfterDays() + 1), DateUtil.FORMAT_DATE);
                                    desc = "当前项目与" + item2.getItemName() + "项目检查时间要求间隔" + itemBefore2.getAfterDays() + "天，只能预约" + afterDate + "以前" + str + "的日期，如有疑问，请到护士站咨询。";
                                }
                                if (desc != null) {
                                    return desc;
                                }
                            }
                        }
                    }
                }
            }
        }
        return desc;
    }

    public int getReqDateDefaultBySchedule() {
        String val = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.REQ_DATE_DEFAULT_BY_SCHEDULE.getKey());
        int date = 0;
        if (StringUtils.isNotBlank(val)) {
            date = Integer.parseInt(val);
        }
        return date;
    }

    public int getSigninOvertimeLimit() {
        String value = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.SIGNIN_OVERTIME_CNT.getKey());
        return StringUtils.isNotBlank(value) ? Integer.parseInt(value) : 3;
    }

    /**
     * 将预约成功消息同步给第三方
     *
     * @param ea
     * @param actType
     * @param scheduleStatus
     * @return
     */
    public boolean isScheduleSync(ExamApplyDto ea, String actType, String scheduleStatus) {
        boolean isSyncSchedule = false;
        String notifyThird = getConfigByName(ConstantsUtil.ConfigName.IS_NOTIFY_THIRD_AFTER_SCHEDULE.getKey());
        ConfigDto.NotifyThirdAfterSchedule config = JsonUtil.toBean(notifyThird, ConfigDto.NotifyThirdAfterSchedule.class);

        if (config != null && "0".equals(config.getGrant())) {
            DictUsersDto obj = commonService.dictUsers(ea);
            ea.setScheduler(obj.getName());
            ea.setUserId(obj.getUserId());
            ea.setStaffNo(obj.getStaffNo());
            String timeout = getConfigByName(ConstantsUtil.ConfigName.HTTP_TIMEOUT.getKey());
            if ("0".equals(config.getIsSyncWeChat()) && "0,1,7,2,3,5".contains(actType)) {
                ExecutorService ex = Executors.newSingleThreadExecutor();
                ex.execute(() -> {
                    HttpUtil httpUtil = new HttpUtil();
                    String httpUrl = config.getSyncWeChatUrl();
                    String bodyContent = JsonUtil.toJson(ea);
                    logger.info("实时同步预约信息到微信,URL :{} ,参数 :{}", httpUrl, bodyContent);
                    String result = httpUtil.sendHttpPostBody(httpUrl, bodyContent, timeout);
                    logger.info("实时同步预约信息到微信(响应内容:{})", result);
                    ex.shutdown();
                });
            }
            for (ConfigDto.SyncInfoSet SyncInfoSet : config.getSyncInfoSet()) {
                if (SyncInfoSet.getSyncExamClass().contains(ea.getExamClass()) && SyncInfoSet.getSyncAct().contains(actType)) {
                    isSyncSchedule = true;
                    break;
                }
            }
            // isSyncSchedule = StringUtils.isNotBlank(config.getSyncUrl());
            if ("0".equals(config.getIsSyncRefer())
                    && StringUtils.isNotBlank(ea.getApplyNo())
                    && ea.getApplyNo().startsWith("RE")) {
                isSyncSchedule = false;
            }
            if (isSyncSchedule) {
                if ("0".equals(config.getIsSyncScheduleRealTime())) {
                    ExecutorService ex = Executors.newSingleThreadExecutor();
                    ex.execute(() -> {
                        logger.info("实时同步开始");
                        HttpUtil httpUtil = new HttpUtil();
                        String httpUrl = config.getSyncUrl();
                        String bodyContent = JsonUtil.toJson(ea);
                        logger.info("实时同步预约信息,URL :{} ,参数 :{}", httpUrl, bodyContent);
                        String result = httpUtil.sendHttpPostBody(httpUrl, bodyContent);
                        logger.info("实时同步预约信息(响应内容:{})", result);
                        if (StringUtils.isNotBlank(result)) {
                            JsonResult jsonResult = (JsonResult) JsonUtil.toBean(result, JsonResult.class);
                            if (!"0".equals(jsonResult.getStatus())) {
                                logger.info("同步失败新增日志" + ea.getApplyNos());
                                for (String applyNo : ea.getApplyNos()) {
                                    ExamClinicSynLog log = new ExamClinicSynLog();
                                    log.setRowId(applyNo);
                                    log.setExamStatus(scheduleStatus);
                                    examClinicSynLogService.saveLog(log);
                                }
                            }
                        }
                        ex.shutdown();
                    });
                } else if ("1".equals(config.getIsSyncScheduleRealTime())) {
                    logger.info("实时同步开始");
                    HttpUtil httpUtil = new HttpUtil();
                    String httpUrl = config.getSyncUrl();
                    String bodyContent = JsonUtil.toJson(ea);
                    logger.info("实时同步预约信息,URL :{} ,参数 :{}", httpUrl, bodyContent);
                    String result = httpUtil.sendHttpPostBody(httpUrl, bodyContent, timeout);
                    logger.info("实时同步预约信息(响应内容:{})", result);
                    if (!StringUtils.isNotBlank(result)) {
                        return false;
                    }
                    JsonResult jsonResult = JsonUtil.toBean(result, JsonResult.class);
                    if (!"0".equals(jsonResult.getStatus())) {
                        logger.info("同步失败新增日志" + ea.getApplyNos());
                        for (String applyNo : ea.getApplyNos()) {
                            ExamClinicSynLog clinicSynLog = new ExamClinicSynLog();
                            clinicSynLog.setRowId(applyNo);
                            clinicSynLog.setExamStatus(scheduleStatus);
                            examClinicSynLogService.saveLog(clinicSynLog);
                        }
                        logger.info("同步预约信息失败,取消预约");
                        return false;
                    }
                } else {
                    for (String applyNo : ea.getApplyNos()) {
                        ExamClinicSynLog clinicSynLog = new ExamClinicSynLog();
                        clinicSynLog.setRowId(applyNo);
                        clinicSynLog.setExamStatus(scheduleStatus);
                        examClinicSynLogService.saveLog(clinicSynLog);
                    }
                }
            } else {
                for (String applyNo : ea.getApplyNos()) {
                    ExamClinicSynLog synLog = new ExamClinicSynLog();
                    synLog.setRowId(applyNo);
                    synLog.setExamStatus(scheduleStatus);
                    examClinicSynLogService.saveLog(synLog);
                }
            }
        }
        return true;
    }

    /***
     * 在综合号码输入号码时增加前缀
     * @param icCard
     * @return
     */
    public String icCardPre(String icCard) {
        if (StringUtils.isNotBlank(icCard)) {
            icCard = icCard.trim();
            List<ConfigDto.IcCardPreScope> list = JsonUtil.toList(getConfigByName(ConstantsUtil.ConfigName.IC_CARD_PRES.getKey()), ConfigDto.IcCardPreScope.class);
            if (list != null && list.size() > 0) {
                for (ConfigDto.IcCardPreScope icCardPreScope : list) {
                    if (!StringUtils.isBlank(icCardPreScope.getLength())) {
                        if (StringUtils.isBlank(icCardPreScope.getCardPre())) {
                            continue;
                        }
                        if (icCard.length() == Integer.parseInt(icCardPreScope.getLength())) {
                            return icCardPreScope.getCardPre() + icCard;
                        }
                        continue;
                    }
                }
            }
        }
        return icCard;
    }

    /**
     * 判断是否在预约后进行凭条打印提示
     *
     * @param ea 申请单信息
     * @return bool true 提示 false 不提示
     * @author ljy
     */
    public boolean isRemindPrint4Schedule(ExamApplyDto ea) {
        boolean isRemindPrint = false;
        List<ConfigDto.PrintTicketAfterSchedule> remindPrintTicketAfterScheduleList = JsonUtil.toList(getConfigByName(ConstantsUtil.ConfigName.REMIND_PRINT_TICKET_AFTER_SCHEDULE.getKey()), ConfigDto.PrintTicketAfterSchedule.class);
        if (CollectionUtils.isNotEmpty(remindPrintTicketAfterScheduleList)) {
            List<ConfigDto.PrintTicketAfterSchedule> afterScheduleList = remindPrintTicketAfterScheduleList.stream().filter(x -> x.getPrintTicketTerminalType().equals(ea.getTerminalType()))
                    .filter(x -> CollectionUtils.isEmpty(x.getPrintTicketExamClass()) || (CollectionUtils.isNotEmpty(x.getPrintTicketExamClass()) && x.getPrintTicketExamClass().contains(ea.getExamClass())))
                    .filter(x -> CollectionUtils.isEmpty(x.getPrintTicketPatientSource()) || (CollectionUtils.isNotEmpty(x.getPrintTicketPatientSource()) && x.getPrintTicketPatientSource().contains(ea.getPatientSource())))
                    .collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(afterScheduleList)) {
                isRemindPrint = true;
            }
        }
        return isRemindPrint;
    }

    public boolean isRemindPrint4Sign(ExamApplyDto ea) {
        boolean isRemindPrint = false;
        List<ConfigDto.PrintTicketAfterSign> remindPrintTicketAfterSignList = JsonUtil.toList(getConfigByName(ConstantsUtil.ConfigName.REMIND_PRINT_TICKET_AFTER_SIGN.getKey()), ConfigDto.PrintTicketAfterSign.class);
        if (CollectionUtils.isNotEmpty(remindPrintTicketAfterSignList)) {
//            List<ConfigDto.PrintTicketAfterSign> afterScheduleList = remindPrintTicketAfterSignList.stream()
//                    .filter(x -> x.getPrintTicketTerminalType().equals(ea.getTerminalType()))
//                    .filter(x -> CollectionUtils.isNotEmpty(x.getPrintTicketExamClass()) || (CollectionUtils.isNotEmpty(x.getPrintTicketExamClass()) && x.getPrintTicketExamClass().contains(ea.getExamClass())))
//                    .filter(x -> CollectionUtils.isEmpty(x.getPrintTicketPatientSource()) || (CollectionUtils.isNotEmpty(x.getPrintTicketPatientSource()) && x.getPrintTicketPatientSource().contains(ea.getPatientSource())))
//                    .collect(Collectors.toList());
//            if (CollectionUtils.isNotEmpty(afterScheduleList)) {
//                isRemindPrint = true;
//            }

            for (ConfigDto.PrintTicketAfterSign ticketAfterSign : remindPrintTicketAfterSignList) {
                if (Objects.nonNull(ticketAfterSign.getPrintTicketTerminalType())
                        && ticketAfterSign.getPrintTicketTerminalType().equals(ea.getTerminalType())) {
                    if (CollectionUtils.isNotEmpty(ticketAfterSign.getPrintTicketExamClass()) && CollectionUtils.isNotEmpty(ticketAfterSign.getPrintTicketPatientSource())) {
                        if (ticketAfterSign.getPrintTicketExamClass().contains(ea.getExamClass()) && ticketAfterSign.getPrintTicketPatientSource().contains(ea.getPatientSource())) {
                            isRemindPrint = true;
                            break;
                        }
                    } else if (CollectionUtils.isNotEmpty(ticketAfterSign.getPrintTicketExamClass())) {
                        if (ticketAfterSign.getPrintTicketExamClass().contains(ea.getExamClass())) {
                            isRemindPrint = true;
                            break;
                        }
                    } else if (CollectionUtils.isNotEmpty(ticketAfterSign.getPrintTicketPatientSource())) {
                        if (ticketAfterSign.getPrintTicketPatientSource().contains(ea.getPatientSource())) {
                            isRemindPrint = true;
                            break;
                        }
                    } else if (CollectionUtils.isEmpty(ticketAfterSign.getPrintTicketExamClass())
                            && CollectionUtils.isEmpty(ticketAfterSign.getPrintTicketPatientSource())) {
                        isRemindPrint = true;
                        break;
                    }
                }
            }
        }
        return isRemindPrint;
    }

    public Map<String, Object> isSignScheduleByThirdWS(ExamApplyDto examApplyDto) {
        Map<String, Object> map = new HashMap<>();
        map.put("isSignScheduleByThirdWS", false);
        String isSignScheduleByThirdWS = getConfigByName(ConstantsUtil.ConfigName.IS_SIGN_SCHEDULE_BY_THIRD_WS.getKey());
        if (StringUtils.isBlank(isSignScheduleByThirdWS)) {
            return map;
        }
        ConfigDto.SignScheduleByThirdWS signScheduleByThirdWS = JsonUtil.toBean(isSignScheduleByThirdWS, ConfigDto.SignScheduleByThirdWS.class);
        if (!"0".equals(signScheduleByThirdWS.getGrant()) || signScheduleByThirdWS.getSignInfoSet() == null) {
            return map;
        }
        String signUrl = signScheduleByThirdWS.getSignUrl();
        String cancelUrl = (signScheduleByThirdWS.getCancelUrl() != null) ? signScheduleByThirdWS.getCancelUrl() : "";
        for (ConfigDto.SignInfoSet signInfoSet : signScheduleByThirdWS.getSignInfoSet()) {
            if (signInfoSet.getSignExamClass().contains(examApplyDto.getExamClass())) {
                map.put("isSignScheduleByThirdWS", true);
                map.put("signUrl", signUrl);
                map.put("cancelUrl", cancelUrl);
                String queueNoSub = (signInfoSet.getQueueNoSub() != null) ? String.valueOf(signInfoSet.getQueueNoSub()) : "";
                map.put("queueNoSub", queueNoSub);
                break;
            }
        }
        return map;
    }

    public String getAccountBalance(ExamApplyPatientDto ep) {
        String result = "", responseStr = "";
        if ("0".equals(getConfigByName(ConstantsUtil.ConfigName.IS_GET_ACCOUNT_BALANCE_REALTIME.getKey()))) {
            String httpUrl = getConfigByName(ConstantsUtil.ConfigName.GET_ACCOUNT_BALANCE_REALTIME_URL.getKey());
            String bodyContent = JsonUtil.toJson(ep);
            String timeout = getConfigByName(ConstantsUtil.ConfigName.HTTP_TIMEOUT.getKey());
            logger.info("获取患者账户余额,URL :{} ,参数 :{}", httpUrl, bodyContent);
            try {
                HttpUtil httpUtil = new HttpUtil();
                responseStr = httpUtil.sendHttpPostBody(httpUrl, bodyContent, timeout);
                logger.info("获取患者账户余额返回内容:{}", responseStr);
            } catch (ResourceAccessException r) {
                logger.error("获取患者账户余额超时:" + r.getMessage(), r);
                result = "获取患者账户余额超时";
            }
            // 返回内容不为空 解析内容
            if (StringUtils.isNotBlank(responseStr)) {
                JsonResult jsonResult = JsonUtil.toBean(responseStr, JsonResult.class);
                if (!"0".equals(jsonResult.getStatus())) {
                    result = "查询患者账户余额失败";
                } else {
                    JSONObject json = (JSONObject) jsonResult.getResult();
                    ExamApplyPatientDto patientDto = json.toJavaObject(ExamApplyPatientDto.class);
                    result = patientDto.getCardRest();
                }
            }
        }
        return result;
    }

    /**
     * @param examClass
     * @return 获取不冲突的检查类别
     * @description
     * @author ryan.li
     * @date 2022/10/17 16:47
     */
    public List<String> getNoConflictExamClasses(String examClass) {
        List<String> list_ret = new ArrayList<>();
        String noConflictExamClass = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.NO_CONFLICT_EXAM_CLASS.getKey());
        List<ConfigDto.NoConflictExamClass> noConflictExamClassList;
        if (StringUtils.isNotBlank(noConflictExamClass)) {
            noConflictExamClassList = JsonUtil.toList(noConflictExamClass, ConfigDto.NoConflictExamClass.class);
            if (CollectionUtils.isNotEmpty(noConflictExamClassList)) {
                for (ConfigDto.NoConflictExamClass list : noConflictExamClassList) {
                    String noConflictExamC = list.getExamClass();
                    if (examClass.equals(noConflictExamC)) {
                        List<String> excepClass = list.getExcepClass();
                        list_ret.addAll(excepClass);
                    }
                }
            }
        }
        if (CollectionUtils.isEmpty(list_ret)) {
            return null;
        }
        return list_ret;
    }

    /**
     * 是否回收号源 false 不会回收号源 true 回收号源
     * 【取消预约号源不释放】examClass：表示提前报到释放号源的检查类别；leadTime：表示提前时间（界面选什么，就怎样去存进数据库）；
     *
     * @param examClass
     * @param scheduleDate
     * @return
     */
    public boolean getNoFreeSourceByCancel(String examClass, String scheduleDate) {
        boolean isOrgansRecycle = false;
        if (StringUtils.isNotBlank(examClass)) {
            String noFreeSourceByCancel = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.NO_FREE_SOURCE_BY_CANCEL.getKey());
            if (StringUtils.isNotBlank(noFreeSourceByCancel)) {
                List<ConfigDto.NoFreeSourceByCancel> noFreeSourceByCancelList = JsonUtil.toList(noFreeSourceByCancel, ConfigDto.NoFreeSourceByCancel.class);
                if (CollectionUtils.isNotEmpty(noFreeSourceByCancelList)) {
                    for (ConfigDto.NoFreeSourceByCancel list : noFreeSourceByCancelList) {
                        if (list.getExamClass().contains(examClass)) {
                            int day = -1;
                            if (StringUtils.isNotBlank(list.getLeadTime())) {
                                day = Integer.parseInt(list.getLeadTime().substring(0, list.getLeadTime().length() - 1));
                            }
                            try {
                                if (day == -1) {
                                    isOrgansRecycle = true;
                                } else {
                                    int nDay = DateUtil.getIntervalDays(scheduleDate, DateUtil.date2Str(new Date(), "yyyy-MM-dd"));
                                    if (nDay > -1 && day >= nDay) {
                                        isOrgansRecycle = true;
                                    }
                                }
                            } catch (Exception e) {
                                logger.info("号源取消操作日期型字符串格式错误");
                            }
                            break;
                        }
                    }
                }
            }
        }
        return isOrgansRecycle;
    }

    /**
     * 判断是否需要先缴费才能预约的项目或者预约渠道
     * 终端、检查类型、患者来源
     * 如果三个有值则三个条件都需要满足
     *
     * @param ea
     * @return
     */
    public boolean getChargeFirstSchedule(ExamApplyDto ea) {
        boolean isChargeFirst = false;
        String chargeFirstTerminalType = getConfigByName(ConstantsUtil.ConfigName.CHARGE_FIRST_TERMINAL_TYPE.getKey());
        String chargeFirstExamClass = getConfigByName(ConstantsUtil.ConfigName.CHARGE_FIRST_EXAM_CLASS.getKey());
        String chargeFirstPatientSource = getConfigByName(ConstantsUtil.ConfigName.CHARGE_FIRST_PATIENT_SOURCE.getKey());
        if (StringUtils.isNotBlank(chargeFirstTerminalType)) {
            if (StringUtils.isNotBlank(chargeFirstExamClass)) {
                if (StringUtils.isNotBlank(chargeFirstPatientSource)) {
                    if (chargeFirstTerminalType.contains(ea.getTerminalType()) && chargeFirstExamClass.contains(ea.getExamClass()) && chargeFirstPatientSource.contains(ea.getPatientSource())) {
                        isChargeFirst = true;
                    }
                } else if (chargeFirstTerminalType.contains(ea.getTerminalType()) && chargeFirstExamClass.contains(ea.getExamClass())) {
                    isChargeFirst = true;
                }
            } else if (StringUtils.isNotBlank(chargeFirstPatientSource)) {
                if (chargeFirstTerminalType.contains(ea.getTerminalType()) && chargeFirstPatientSource.contains(ea.getPatientSource())) {
                    isChargeFirst = true;
                }
            } else if (chargeFirstTerminalType.contains(ea.getTerminalType())) {
                isChargeFirst = true;
            }
        } else if (StringUtils.isNotBlank(chargeFirstExamClass)) {
            if (StringUtils.isNotBlank(chargeFirstPatientSource)) {
                if (chargeFirstExamClass.contains(ea.getExamClass()) && chargeFirstPatientSource.contains(ea.getPatientSource())) {
                    isChargeFirst = true;
                }
            } else if (chargeFirstExamClass.contains(ea.getExamClass())) {
                isChargeFirst = true;
            }
        } else if (StringUtils.isNotBlank(chargeFirstPatientSource) && chargeFirstPatientSource.contains(ea.getPatientSource())) {
            isChargeFirst = true;
        }
        return isChargeFirst;
    }


    /**
     * 去掉已预约 超时且没有报道的数据
     *
     * @param ea
     * @param items
     * @param terminalType
     * @return
     */
    public ExamApplyDto noShowScheduleItem(ExamApplyDto ea, List<ExamApplyItemDto> items, String terminalType) {
        String noShowUnScheduleItemByTerminalType = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.NO_SHOW_UN_SCHEDULE_ITEM_BY_TERMINAL_TYPE.getKey());
        String noShowOnlyDeptscheScheduleByTerminalType = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.NO_SHOW_ONLY_DEPTSCHE_SCHEDULE_BY_TERMINAL_TYPE.getKey());
        Iterator<ExamApplyItemDto> it = items.iterator();
        while (it.hasNext()) {
            ExamApplyItemDto eai = it.next();
            if (StringUtils.isNotBlank(eai.getScheduledId())) {
                continue;
            }
            if (StringUtils.isNotBlank(noShowUnScheduleItemByTerminalType)) {
                List<String> list = Arrays.asList(noShowUnScheduleItemByTerminalType.split(","));
                if (list.contains(terminalType)) {
                    String flag = CommonUtil.subFlags(eai.getFlags(), 1);
                    if ("1".equals(flag)) {
                        it.remove();
                    }
                }
            }
            if (!StringUtils.isNotBlank(noShowOnlyDeptscheScheduleByTerminalType)) {
                continue;
            }
            List<String> list = Arrays.asList(noShowOnlyDeptscheScheduleByTerminalType.split(","));
            if (!list.contains(terminalType)) {
                continue;
            }
            String flag = CommonUtil.subFlags(eai.getFlags(), 1);
            if (!"2".equals(flag)) {
                continue;
            }
            it.remove();
        }
        if (items.size() > 0) {
            return ea;
        }
        return null;
    }

    /**
     * 获取不能同一天检查的项目
     * resultMap.put("examClass", "当天已预约了 不能和镇静/增强同一天的检查");
     * resultMap.put("itemName", itemName);
     * resultMap.put("message", "项目冲突，请选择其他日期");
     * resultMap.put("title", "不能和镇静/增强同一天检查的项目");
     *
     * @param ea
     * @return
     */
    public Map<String, Object> noOneDayItem(ExamApplyDto ea) {
        Map<String, Object> resultMap = new HashMap<>();
        String value = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.NO_ONE_DAY_CLAM_OR_ENHANCE_ITEM.getKey());
        if (StringUtils.isNotBlank(value)) {
            //Map<String, String> map = new HashMap<>();
            String scheduleDate = ea.getScheduleDate();
            ExamApplyDto e = new ExamApplyDto();
            e.setStartDate(scheduleDate);
            e.setEndDate(scheduleDate);
            e.setSickId(ea.getSickId());
            List<ExamApplyItemDto> otherItems = examApplyItemServiceImpl.selectOtherSchedule(e);
            if (otherItems == null || otherItems.size() == 0) {
                return resultMap;
            }
            List<String> clamItemCode = new ArrayList<String>();
            List<String> enhanceItemCode = new ArrayList<String>();
            List<ConfigDto.NoOneDayClamOrEnhanceItem> noOneDayClamOrEnhanceItemList = JsonUtil.toList(value, ConfigDto.NoOneDayClamOrEnhanceItem.class);
            for (ConfigDto.NoOneDayClamOrEnhanceItem list : noOneDayClamOrEnhanceItemList) {
                String itemFlag = list.getItemFlag();
                if ("1".equals(itemFlag)) {
                    List<DictExamItem> clamItem = list.getExamItem();
                    if (CollectionUtils.isNotEmpty(clamItem)) {
                        for (DictExamItem dei : clamItem) {
                            clamItemCode.add(dei.getItemCode());
                        }
                    }
                } else {
                    if (!"2".equals(itemFlag)) {
                        continue;
                    }
                    List<DictExamItem> enhanceItem = list.getExamItem();
                    for (DictExamItem dei : enhanceItem) {
                        enhanceItemCode.add(dei.getItemCode());
                    }
                }
            }
            List<String> otherClam = new ArrayList<String>();
            List<String> otherEnhance = new ArrayList<String>();
            List<String> otherClamItem = new ArrayList<String>();
            List<String> otherEnhanceItem = new ArrayList<String>();
            List<String> otherClamApply = new ArrayList<String>();
            for (ExamApplyItemDto item : otherItems) {
                String clamFlag = CommonUtil.subFlags(item.getFlags(), 2);
                if ("1".equals(clamFlag)) {
                    otherClam.add(item.getItemName());
                }
                String clamApplyFlag = CommonUtil.subFlags(item.getApplyFlags(), 16);
                if ("1".equals(clamApplyFlag)) {
                    otherClamApply.add(item.getItemName());
                }
                String enhanceFlag = CommonUtil.subFlags(item.getFlags(), 3);
                if ("1".equals(enhanceFlag)) {
                    otherEnhance.add(item.getItemName());
                }
                if (clamItemCode.contains(item.getItemCode())) {
                    otherClamItem.add(item.getItemName());
                }
                if (enhanceItemCode.contains(item.getItemCode())) {
                    otherEnhanceItem.add(item.getItemName());
                }
            }
            boolean isClam = false;
            boolean isEnhance = false;
            boolean isClamItem = false;
            boolean isEnhanceItem = false;
            for (ExamApplyItemDto item2 : ea.getItems()) {
                String enhanceFlag2 = CommonUtil.subFlags(item2.getFlags(), 3);
                if ("1".equals(enhanceFlag2)) {
                    isEnhance = true;
                }
                String clamFlag2 = CommonUtil.subFlags(item2.getFlags(), 2);
                if ("1".equals(clamFlag2)) {
                    isClam = true;
                }
                if (clamItemCode.contains(item2.getItemCode())) {
                    isClamItem = true;
                }
                if (enhanceItemCode.contains(item2.getItemCode())) {
                    isEnhanceItem = true;
                }
            }
            String itemName = "";
            if (isClam && otherClamItem.size() > 0) {
                itemName = StringUtils.join(otherClamItem, ",");
            }
            if (isEnhance && otherEnhanceItem.size() > 0) {
                itemName = StringUtils.join(otherEnhanceItem, ",");
            }
            if (isClamItem && otherClam.size() > 0) {
                itemName = StringUtils.join(otherClam, ",");
            }
            if (isEnhanceItem && otherEnhance.size() > 0) {
                itemName = StringUtils.join(otherEnhance, ",");
            }
            if (isClamItem && otherClamApply.size() > 0) {
                itemName = StringUtils.join(otherClamApply, ",");
            }
            if (StringUtils.isBlank(itemName)) {
                ExamApplyDto applyDto = new ExamApplyDto();
                applyDto.setApplyNos(ea.getApplyNos());
                List<ExamApplyDto> applyList = examApplyMapper.getList(applyDto);
                boolean isClamApply = false;
                for (ExamApplyDto apply : applyList) {
                    String clamApplyFlag2 = CommonUtil.subFlags(apply.getFlags(), 16);
                    if ("1".equals(clamApplyFlag2)) {
                        isClamApply = true;
                        break;
                    }
                }
                if (isClamApply && otherClamItem.size() > 0) {
                    itemName = StringUtils.join(otherClamItem, ",");
                }
            }
            if (StringUtils.isNotBlank(itemName)) {
                resultMap.put("examClass", "当天已预约了 不能和镇静/增强同一天的检查");
                resultMap.put("itemName", itemName);
                resultMap.put("message", "项目冲突，请选择其他日期");
                resultMap.put("title", "不能和镇静/增强同一天检查的项目");
            }
        }
        return resultMap;
    }

    public Map<String, Object> noOneDayEnhanceOrClam(ExamApplyDto ea) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        String enhanceValue = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.IS_NO_ONE_DAY_ENHANCE.getKey());
        String clamValue = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.IS_NO_ONE_DAY_CLAM.getKey());
        if (!"0".equals(enhanceValue) && !"0".equals(clamValue)) {
            return resultMap;
        }
        boolean isEnhanceItem = false;
        boolean isClamItem = false;
        for (ExamApplyItemDto item : ea.getItems()) {
            String enhanceFlag = CommonUtil.subFlags(item.getFlags(), 3);
            if ("1".equals(enhanceFlag)) {
                isEnhanceItem = true;
            }
            String clamFlag = CommonUtil.subFlags(item.getFlags(), 2);
            if ("1".equals(clamFlag)) {
                isClamItem = true;
            }
        }
        Map<String, String> map = new HashMap<String, String>();
        String scheduleDate = ea.getScheduleDate();
        ExamApplyDto e = new ExamApplyDto();
        e.setStartDate(scheduleDate);
        e.setEndDate(scheduleDate);
        e.setSickId(ea.getSickId());
        List<ExamApplyItemDto> otherItems = examApplyItemServiceImpl.selectOtherSchedule(e);
        if (otherItems == null || otherItems.size() == 0) {
            return resultMap;
        }
        List<String> mergeNos = (List<String>) CommonUtil.split2List(ea.getMergeNo());
        Iterator<ExamApplyItemDto> it = otherItems.iterator();
        if ("0".equals(enhanceValue) && isEnhanceItem) {
            String msg = "【" + ea.getScheduleApm() + "】时段已预约增强的检查";
            while (it.hasNext()) {
                ExamApplyItemDto item2 = it.next();
                String enhanceFlag2 = CommonUtil.subFlags(item2.getFlags(), 3);
                if (!mergeNos.contains(item2.getMergeNo()) && "1".equals(enhanceFlag2)) {
                    if (StringUtils.isBlank(item2.getScheduleDate())) {
                        continue;
                    }
                    resultMap.put("examClass", msg);
                    resultMap.put("itemName", item2.getItemName());
                    resultMap.put("message", "增强冲突，请选择其他日期");
                    resultMap.put("title", "所需增强的项目不能同一天检查");
                    return resultMap;
                }
            }
        }
        if ("0".equals(clamValue)) {
            String msg = "【" + ea.getScheduleApm() + "】时段已预约镇静的检查";
            if (isClamItem) {
                isClamItem = false;
                while (it.hasNext()) {
                    ExamApplyItemDto item2 = it.next();
                    String clamFlag2 = CommonUtil.subFlags(item2.getFlags(), 2);
                    if (!mergeNos.contains(item2.getMergeNo()) && "1".equals(clamFlag2)) {
                        if (StringUtils.isBlank(item2.getScheduleDate())) {
                            continue;
                        }
                        resultMap.put("examClass", msg);
                        resultMap.put("itemName", item2.getItemName());
                        resultMap.put("message", "镇静冲突，请选择其他日期");
                        resultMap.put("title", "所需镇静的项目不能同一天检查");
                        return resultMap;
                    }
                }
            }
            boolean isClamApply = false;
            List<String> itemName = new ArrayList<String>();
            while (it.hasNext()) {
                ExamApplyItemDto item3 = it.next();
                String clamApplyFlag = CommonUtil.subFlags(item3.getApplyFlags(), 16);
                if ("1".equals(clamApplyFlag)) {
                    isClamApply = true;
                    itemName.add(item3.getItemName());
                }
            }
            if (isClamApply) {
                ExamApplyDto applyDto = new ExamApplyDto();
                applyDto.setApplyNos(ea.getApplyNos());
                List<ExamApplyDto> applyList = examApplyMapper.getList(applyDto);
                isClamApply = false;
                for (ExamApplyDto apply : applyList) {
                    String clamApplyFlag2 = CommonUtil.subFlags(apply.getFlags(), 16);
                    if ("1".equals(clamApplyFlag2)) {
                        resultMap.put("examClass", msg);
                        resultMap.put("itemName", itemName);
                        resultMap.put("message", "镇静冲突，请选择其他日期");
                        resultMap.put("title", "所需镇静的申请单不能同一天检查");
                        return resultMap;
                    }
                }
            }
        }
        return resultMap;
    }

    /**
     * 获取申请单镇静需要的时间
     * 镇静申请单只可预约相应时长后的时段 examClass：表示检查类别，limitTime：表示只能预约“N”小时之后(带单位时间)
     *
     * @param examClass 检查类别
     * @param applyNos  申请单
     * @return 小时
     */
    public int getClamBeforesTime(String examClass, List<String> applyNos) {
        int clamBeforesTime = 0;
        if (applyNos == null || applyNos.size() == 0) {
            return clamBeforesTime;
        }
        String paramValue = getConfigByName(ConstantsUtil.ConfigName.ONLY_MATCH_APM_BY_CLAM_APPLY.getKey());
        if (StringUtils.isNotBlank(paramValue)) {
            List<ConfigDto.CommonSet> commonSetList = JsonUtil.toList(paramValue, ConfigDto.CommonSet.class);
            if (CollectionUtils.isNotEmpty(commonSetList)) {
                for (ConfigDto.CommonSet commonSet : commonSetList) {
                    if (commonSet != null) {
                        List<String> examClassList = commonSet.getExamClass();
                        if (!examClassList.contains(examClass)) {
                            continue;
                        }
                        // 是否镇静
                        boolean isClam = false;
                        ExamApplyDto d = new ExamApplyDto();
                        d.setApplyNos(applyNos);
                        // 根据申请单号获取申请单信息
                        List<ExamApplyDto> examApplyList = examApplyMapper.getList(d);
                        if (CollectionUtils.isNotEmpty(examApplyList)) {
                            for (ExamApplyDto ea : examApplyList) {
                                String flag = CommonUtil.subFlags(ea.getFlags(), 16);
                                if ("1".equals(flag)) {
                                    isClam = true;
                                    break;
                                }
                            }
                        }
                        if (isClam) {
                            clamBeforesTime = Integer.parseInt(commonSet.getValue());
                            if ("天".equals(commonSet.getUnit())) {
                                clamBeforesTime = clamBeforesTime * 24;
                            }
                            return clamBeforesTime;
                        }
                    }
                }
            }
        }
        return clamBeforesTime;
    }

    /**
     * @param dto
     * @return
     * @description 获取是否可以有其他预约选项
     * @author ryan.li
     * @date 2022/10/17 16:52
     */
    public Map<String, Object> hasOtherSchedule(ExamApplyDto dto) {
        Map<String, Object> resultMap = new HashMap<>();
        ExamScheduleDto es = new ExamScheduleDto();
        String scheduleDate = dto.getScheduleDate();
        es.setScheduledDate(scheduleDate);
        es.setExamClass(dto.getExamClass());
        es.setPerformDept(dto.getPerformDept());
        // 返回不冲突的检查类别的项目
        es.setNoConflictClasses(getNoConflictExamClasses(dto.getExamClass()));

        es.setApplyNos(dto.getApplyNos());
        es.setApplyNo(dto.getApplyNo());

        QueryWrapper<ExamApply> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("APPLY_NO", dto.getApplyNo());
        ExamApply examApply = examApplyMapper.selectOne(queryWrapper);
        if (Objects.nonNull(examApply)) {
            es.setSickId(examApply.getSickId());
        } else {
            throw new BusinessException("数据错误-没找到申请单!");
        }
        // 获取患者当日的其他检查类型的检查项目
        List<ExamScheduleDto> otherItemList = examScheduleMapper.getExamScheduleOtherApm(es);
        if (CollectionUtils.isNotEmpty(otherItemList)) {
            int intervalTime = 0;
            List<String> examClassL = new ArrayList<>();
            List<String> itemNameL = new ArrayList<>();
            List<String> itemNameF = new ArrayList<>();
            List<String> scheduleApm = new ArrayList<>();
            int st = Integer.parseInt(dto.getStartTime().replace(":", ""));
            int et = Integer.parseInt(dto.getEndTime().replace(":", ""));
            if (!"00:00".equals(dto.getStartTime()) && "00:00".equals(dto.getEndTime())) {
                et = 2400;
            }
            for (ExamScheduleDto d : otherItemList) {
                String timeStart = d.getTimeStart();
                String tiemEnd = d.getTimeEnd();
                int st2 = Integer.parseInt(timeStart.replace(":", ""));
                int et2 = Integer.parseInt(tiemEnd.replace(":", ""));
                if (!"00:00".equals(timeStart) && "00:00".equals(tiemEnd)) {
                    et2 = 2400;
                }
                if ((st > st2 && st < et2) || (et > st2 && et < et2) || (st <= st2 && et >= et2)) {
                    if (!examClassL.contains(d.getExamClass())) {
                        examClassL.add(d.getExamClass());
                    }
                    if (itemNameL.contains(d.getItemName())) {
                        continue;
                    }
                    itemNameL.add(d.getItemName());
                } else {
                    String intervalTimeValue = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.NO_CONFLICT_INTERVAL_TIME.getKey());
                    if (StringUtils.isNotBlank(intervalTimeValue)) {
                        intervalTime = Integer.parseInt(intervalTimeValue);
                    }
                    // 获取两个时间的时间差-分钟
                    String startTime = scheduleDate + " " + dto.getStartTime();
                    String endTime = scheduleDate + " " + timeStart;
                    // 时间差
                    int intervalMinus = DateUtil.getIntervalMinus(startTime, endTime);
                    if (intervalTime <= 0 || intervalMinus >= intervalTime) {
                        continue;
                    }
                    if (!itemNameF.contains(d.getItemName())) {
                        itemNameF.add(d.getItemName());
                    }
                    if (scheduleApm.contains(d.getScheduleApm())) {
                        continue;
                    }
                    scheduleApm.add(d.getScheduleApm());
                }
            }
            if (itemNameL != null && itemNameL.size() > 0) {
                resultMap.put("title", "不同检查类别项目冲突");
                resultMap.put("examClass", "【" + dto.getScheduleApm() + "】时段已预约" + String.join(",", examClassL) + "的检查");
                resultMap.put("itemName", itemNameL);
                resultMap.put("message", "类别冲突，请选择其他时段");
            } else if (itemNameF != null && itemNameF.size() > 0) {
                resultMap.put("title", "不同检查的类别间隔时间冲突");
                resultMap.put("examClass", "已约时段：" + String.join(",", scheduleApm));
                resultMap.put("itemName", itemNameF);
                resultMap.put("message", "不同检查的类别需要间隔" + intervalTime + "分钟，请选择其他时段");
            }
        }
        return resultMap;
    }

    /**
     * 是否需要获取预约排队号
     *
     * @param patientSource
     * @param queueName
     * @return
     */
    public Boolean isGetQueueNoFirst(String patientSource, String queueName) {
        boolean bool1 = false;
        boolean bool2 = false;
        String configStr = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.IS_TAKE_NO_QUEUE.getKey());
        if (StringUtils.isNotBlank(configStr)) {
            ConfigDto.TakeNoQueue configInfo = JsonUtil.toBean(configStr, ConfigDto.TakeNoQueue.class);
            if (!"0".equals(configInfo.getGrant())) {
                return false;
            }
            if (configInfo.getOpenPatientSource() == null || configInfo.getOpenPatientSource().contains(patientSource)) {
                bool1 = true;
            }
            if (configInfo.getOpenQueue() == null) {
                bool2 = true;
            }
            if (configInfo.getOpenQueue() != null) {
                for (DictExamQueue dictExamQueue : configInfo.getOpenQueue()) {
                    if (dictExamQueue.getQueueName().contains(queueName)) {
                        bool2 = true;
                        break;
                    }
                }
            }
        }
        return bool1 && bool2;
    }

    /**
     * 检查类别是否 【以天数为单位判断队列优先级的类别】
     * true 是
     * false 否
     *
     * @param examClass
     * @return
     */
    public boolean isPriorityFirstByDay(String examClass) {
        boolean isPriorityFirstByDay = false;
        String configStr = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.FIRST_SCHE_PRIORITY_QUEUE_BY_ONE_DAY.getKey());
        List<String> list = CommonUtil.split2List(configStr);
        if (CollectionUtils.isNotEmpty(list) && list.contains(examClass)) {
            isPriorityFirstByDay = true;
        }
        return isPriorityFirstByDay;
    }

    /**
     * 验证预约限制配置
     *
     * @param ea
     * @return 返回空字符串则说明 限制没有生效 否则为触发限制错误
     */
    public String scheduleLimit2(ExamApplyDto ea) {
        if (!ConstantsUtil.TerminalType.SELF.getType().equals(ea.getTerminalType())
                && !ConstantsUtil.TerminalType.MOBILE.getType().equals(ea.getTerminalType())) {
            return "";
        }

        int scheCancel = 0;
        // 找到预约条目的最大取消次数
        for (ExamApplyItem eai : ea.getItems()) {
            int sche = (eai.getScheCancel() == null) ? 0 : eai.getScheCancel();
            if (sche > scheCancel) {
                scheCancel = sche;
            }
        }

        // 获取次数限制配置
        String scheduleLimit = cacheServiceImpl.getConfigByName(ConstantsUtil.ConfigName.SCHEDULE_LIMIT_BY_TERMINAL.getKey());
        if (StringUtils.isNotBlank(scheduleLimit)) {
            List<ConfigDto.ScheduleLimit> scheduleLimitList = JsonUtil.toList(scheduleLimit, ConfigDto.ScheduleLimit.class);
            if (!CollectionUtils.isEmpty(scheduleLimitList)) {
                for (ConfigDto.ScheduleLimit limit : scheduleLimitList) {
                    if (limit.getExamClass().contains(ea.getExamClass()) && scheCancel >= limit.getLimitCount()) {
                        return "该项目自助改约次数已满[已改" + limit.getLimitCount() + "次]，请到科室前台修改或咨询";
                    }
                }
            }
        }
        return "";
    }

    /**
     * 获取设置的提示信息
     *
     * @param configName   配置键值名称 yy_noQueryExamApplyReminder
     * @param deptLocation 诊室地址
     * @param examClass    检查类别
     * @return
     */
    public String customReminder(String configName, String deptLocation, String examClass) {
        String reminder = cacheServiceImpl.getConfigByName(configName);
        if (StringUtils.isNotBlank(reminder)) {
            if (StringUtils.isNotBlank(deptLocation)) {
                reminder = reminder.replace("[location]", deptLocation);
            }
            if (StringUtils.isNotBlank(examClass)) {
                reminder = reminder.replace("[examClass]", examClass);
            }
        }
        return reminder;
    }

    @Override
    public List<String> limitScheduleDay(String classAttr, String applyNo, Integer cureInterval) {
        List<String> dateList = new ArrayList<String>();
        if (!"1".equals(classAttr)) {
            return dateList;
        }
        List<ExamScheduleDto> scheduledDateList = examScheduleMapper.intervalDate(applyNo);
        Integer days;
        if ((days = cureInterval) == null) {
            String cureIntervas = examApplyMapper.cureInterval(applyNo);
            if (StringUtils.isNotBlank(cureIntervas)) {
                days = Integer.parseInt(cureIntervas);
            }
        }
        if (scheduledDateList != null && scheduledDateList.size() > 0 && days != null) {
            Integer day = days - 1;
            for (ExamScheduleDto es : scheduledDateList) {
                String scheduleDate = es.getScheduledDate();
                List<String> list = (List<String>) DateUtil.getIntervalDate(es.getScheduledDate(), (int) day);
                for (String date : list) {
                    if (!dateList.contains(date)) {
                        dateList.add(date);
                    }
                }
            }
        }
        return dateList;
    }

    public boolean isNeedPassWordByDeptsche(ExamApplyDto ea) {
        boolean checkPassword = true;
        if (ConstantsUtil.TerminalType.DEPT.getType().equals(ea.getTerminalType())) {
            String value = getConfigByName(ConstantsUtil.ConfigName.IS_NEED_PASSWORD_BY_DEPTSCHE.getKey());
            if ("0".equals(value)) {
                List<String> examClassList = getConfigListByName(ConstantsUtil.ConfigName.NEED_PASSWORD_EXAM_CLASS_BY_DEPTSCHE.getKey());
                if (examClassList == null || examClassList.size() == 0 || examClassList.contains(ea.getExamClass())) {
                    if (StringUtils.isBlank(ea.getPassword())) {
                        checkPassword = false;
                        return checkPassword;
                    }
                    DictUsersDto dictUsersDto = new DictUsersDto();
                    dictUsersDto.setUserId(ea.getUserId());
                    dictUsersDto.setPassword(ea.getPassword().toUpperCase());
                    List<DictUsers> list = (List<DictUsers>) dictUsersService.getList(dictUsersDto);
                    if (list == null || list.size() == 0) {
                        checkPassword = false;
                    }
                }
            }
        }
        return checkPassword;
    }

    /**
     * 限制自助（移动端和自助机）操作类型验证
     *
     * @param terminalType
     * @param actType
     * @param timeStart
     * @param ea
     * @return
     */
    @Override
    public String isLimitSelfOperate(String terminalType, String actType, String timeStart, ExamApplyDto ea) {
        if (!ConstantsUtil.TerminalType.SELF.getType().equals(terminalType) && !ConstantsUtil.TerminalType.MOBILE.getType().equals(terminalType)) {
            return "";
        }
        if (StringUtils.isNotBlank(ea.getScheduleStatus()) && !"08".equals(ea.getScheduleStatus())) {
            return "";
        }
        if (StringUtils.isBlank(timeStart)) {
            DictScheduleApm apm = dictScheduleApmServiceImpl.selectOneByApmCode(ea.getApmCode());
            timeStart = apm.getTimeStart();
        }
        int classAttr = commonService.getClassAttr(ea.getExamClass());
        String key = ConstantsUtil.ConfigName.SELF_ACT_LIMIT.getKey();
        if (1 == classAttr) {
            key = ConstantsUtil.CureConfigName.SELF_ACT_LIMIT.getKey();
        }
        String selfActLimit = cacheServiceImpl.getConfigByName(key);
        if (StringUtils.isNotBlank(selfActLimit)) {
            List<ConfigDto.SelfActLimit> selfActLimitList = JsonUtil.toList(selfActLimit, ConfigDto.SelfActLimit.class);
            if (!CollectionUtils.isEmpty(selfActLimitList)) {
                for (ConfigDto.SelfActLimit sal : selfActLimitList) {
                    if (!sal.getExamClass().contains(ea.getExamClass()) || !sal.getLimitAct().contains(actType)) {
                        continue;
                    }

                    String actMes = "取消预约";
                    if ("1".equals(actType)) {
                        actMes = "修改预约";
                    }
                    String reg = "[^0-9]";
                    Pattern pp = Pattern.compile(reg);
                    Matcher mr = pp.matcher(sal.getLimitTime());

                    String limitTime = mr.replaceAll("").trim();
                    if (StringUtils.isBlank(limitTime)) {
                        continue;
                    }
                    boolean isLimitDays = sal.getLimitTime().contains("天");
                    DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                    String reminder = customReminder(ConstantsUtil.ConfigName.NOT_ALLOW_EDIT_OR_CANCEL_BEFORE_SCHEDULE_REMINDER.getKey(), ea.getDeptLocation(), "");
                    if (reminder == null) {
                        reminder = "";
                    }
                    if (isLimitDays) {
                        int limitDay = DateUtil.getIntervalDays(df.format(new Date()), ea.getScheduleDate());
                        String reLimitDay = limitTime;
                        if (Integer.parseInt(limitTime) >= limitDay) {
                            if (limitDay == 0) {
                                reLimitDay = "当";
                            }
                            return "检查前" + reLimitDay + "天之内不能" + actMes + " " + reminder;
                        }
                    } else {
                        DateFormat d = new SimpleDateFormat("yyyy-MM-dd HH:mm");
                        String date = ea.getScheduleDate() + " " + timeStart;
                        try {
                            int reLimitMin = DateUtil.getIntervalMinus(d.parse(date), new Date());
                            int minute = Integer.parseInt(limitTime) * 60;
                            if (minute >= reLimitMin) {
                                return "检查前" + limitTime + "小时之内不能" + actMes + " " + reminder;
                            }
                        } catch (ParseException e) {
                            logger.error(e.getMessage(), e);
                        }
                    }
                }
            }
        }
        return "";
    }

    /***
     * 需默认镇静的年龄与项目
     * @param dto
     */
    public void IsNeedClamAgeByItem(ExamApplyDto dto) {
        if (dto.getItems() != null && dto.getAge() != null) {
            List<ExamApplyItemDto> eaItems = dto.getItems();
            String eaAge = dto.getAge();
            String needClamAgeByItemStr = getConfigByName(ConstantsUtil.ConfigName.NEED_CLAM_AGE_BY_ITEM.getKey());
            if (StringUtils.isNotBlank(needClamAgeByItemStr)) {
                List<ConfigDto.NeedClamAgeByItem> needClamAgeByItemList = JsonUtil.toList(needClamAgeByItemStr, ConfigDto.NeedClamAgeByItem.class);
                if (CollectionUtils.isNotEmpty(needClamAgeByItemList)) {
                    for (ConfigDto.NeedClamAgeByItem needClamAgeByItem : needClamAgeByItemList) {
                        if (Objects.nonNull(needClamAgeByItem) && needClamAgeByItem.getAgeScope() != null) {
                            int eaAgeDay = DateUtil.util2Day(eaAge);
                            RuleDto.DayScope dayScope = needClamAgeByItem.getAgeScope();
                            int min = (dayScope.getMin() != null) ? dayScope.getMin() : 0;
                            long max = (dayScope.getMax() != null) ? dayScope.getMax() : (System.currentTimeMillis() / 86400000L);
                            // 不在范围内
                            if (eaAgeDay < min || eaAgeDay > max) {
                                continue;
                            }
                            // 申请单是否 需要镇静
                            for (ExamApplyItemDto eaItem : eaItems) {
                                if (StringUtils.isBlank(dto.getFlags()) || "0".equals(String.valueOf(dto.getFlags().toCharArray()[15]))) {
                                    for (DictExamItem item : needClamAgeByItem.getExamItem()) {
                                        if (item.getExamClass().equals(eaItem.getExamClass()) && item.getItemCode().equals(eaItem.getItemCode()) && item.getItemName().equals(eaItem.getItemName())) {
                                            ExamApplyDto ea = new ExamApplyDto();
                                            ea.setApplyNo(dto.getApplyNo());
                                            ea.setType("15");
                                            ea.setFlag("1");
                                            examApplyService.editApplyFlag(ea);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 解析传入参数
     * 根据传入参数
     *
     * @param dto
     * @return
     */
    public List<String> getInputNewSupport(ExamApplyDto dto) {
        List<String> sickIdList = new ArrayList<>();
        if (StringUtils.isNotBlank(dto.getIcCard())
                || StringUtils.isNotBlank(dto.getSickId())
                || StringUtils.isNotBlank(dto.getOutpatientNo())
                || StringUtils.isNotBlank(dto.getInpatientNo())) {
            // 【是否启用新查询支持的输入框类型】(1：关闭   0：启用)
            String isInputNewSupport = getConfigByName(ConstantsUtil.ConfigName.IS_INPUT_NEW_SUPPORT.getKey());
            if (StringUtils.isNotBlank(isInputNewSupport)) {
                ConfigDto.InputNewSupport inputNewSupport = JsonUtil.toBean(isInputNewSupport, ConfigDto.InputNewSupport.class);
                if (inputNewSupport != null && "0".equals(inputNewSupport.getGrant())) {
                    List<String> inputTypeList = inputNewSupport.getInputType();
                    if (!inputTypeList.isEmpty()) {
                        ExamApplyPatientIdDto eapiDato = new ExamApplyPatientIdDto();
                        if (inputTypeList.contains(ConstantsUtil.PatientDomainId.OUTPATIENT_NO.getKey())
                                && StringUtils.isNotBlank(dto.getOutpatientNo())) {
                            eapiDato.setPatientId(dto.getOutpatientNo());
                            eapiDato.setDomainId(ConstantsUtil.PatientDomainId.OUTPATIENT_NO.value);
                        }
                        if (inputTypeList.contains(ConstantsUtil.PatientDomainId.INPATIENT_NO.getKey())
                                && StringUtils.isNotBlank(dto.getInpatientNo())) {
                            eapiDato.setPatientId(dto.getInpatientNo());
                            eapiDato.setDomainId(ConstantsUtil.PatientDomainId.INPATIENT_NO.value);
                        }
                        if (inputTypeList.contains(ConstantsUtil.PatientDomainId.IC_CARD.getKey())
                                && StringUtils.isNotBlank(dto.getIcCard())) {
                            eapiDato.setPatientId(dto.getIcCard());
                            eapiDato.setDomainId(ConstantsUtil.PatientDomainId.IC_CARD.value);
                        }
                        if (StringUtils.isNotBlank(eapiDato.getPatientId()) && StringUtils.isNotBlank(eapiDato.getDomainId())) {
                            List<ExamApplyPatientId> eapiList = examApplyPatientIdService.selectList(eapiDato);
                            if (eapiList != null && !eapiList.isEmpty()) {
                                for (ExamApplyPatientId examApplyPatientId : eapiList) {
                                    sickIdList.add(examApplyPatientId.getSickId());
                                }
                                if (!CollectionUtils.isEmpty(sickIdList)) {
                                    dto.setOutpatientNo(null);
                                    dto.setInpatientNo(null);
                                    dto.setIcCard(null);
                                }
                            }
                        }
                    }
                }
            }
        }
        return sickIdList;
    }

    public void toUpperCaseInput(Object req) {
        boolean isUpperCaseInput = isOpenConfig(ConstantsUtil.ConfigName.IS_UPPER_CASE_INPUT.getKey());
        if (isUpperCaseInput) {
            List<Field> fieldList = new ArrayList<>();
            for (Class<?> tempClass = req.getClass(); tempClass != null; tempClass = tempClass.getSuperclass()) {
                fieldList.addAll(Arrays.asList(tempClass.getDeclaredFields()));
            }
            for (Field field : fieldList) {
                field.setAccessible(true);
                try {
                    if (field.getType() != String.class) {
                        continue;
                    }
                    Object value = field.get(req);
                    if (value == null || (!"applyNo".equals(field.getName()) && !"outpatientNo".equals(field.getName()) && !"inpatientNo".equals(field.getName()) && !"icCard".equals(field.getName()) && !"icCard2".equals(field.getName()) && !"orderNo".equals(field.getName()) && !"commonCard".equals(field.getName()))) {
                        continue;
                    }
                    String decValue = value.toString().toUpperCase();
                    field.set(req, decValue);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public boolean isDeptNotice(String patientSource) {
        boolean bool = false;
        if (isOpenConfig(ConstantsUtil.ConfigName.IS_MESSAGE_ALERT.getKey())) {
            String patientSourceIn = getConfigByName(ConstantsUtil.ConfigName.PATIENT_SOURCE_IN.getKey());
            if (isOpenConfig(ConstantsUtil.ConfigName.IS_MESSAGE_ALERT_BY_WARD.getKey()) && Objects.equals((patientSourceIn != null) ? patientSourceIn : "住院", patientSource)) {
                bool = true;
            }
        }
        return bool;
    }

    /**
     * 当前时段剩余得号源数量
     * 根据当前时间动态减少号源
     *
     * @param date
     * @param timeStart
     * @param timeEnd
     * @param maxLimit
     * @param apmRecycle
     * @return
     */
    public double currentRemainCount(String date, String timeStart, String timeEnd, double maxLimit, double apmRecycle) {
        double currentRemainCount = -1.0;
        // 预约当前时段的号源时根据当前时间动态减少号源
        String isDynamicSource = getConfigByName(ConstantsUtil.ConfigName.IS_DYNAMIC_SOURCE.getKey());
        if ("0".equals(isDynamicSource)) {
            String startDate = date + " " + timeStart;
            String endDate = date + " " + timeEnd;
            if (DateUtil.isEffectiveDate(startDate, endDate, DateUtil.FORMAT_DATETIME)) {
                Date timeEndDate = DateUtil.parseDateV2(timeEnd, "HH:mm");
                Date timeStartDate = DateUtil.parseDateV2(timeStart, "HH:mm");
                Date timeCurrDate = DateUtil.parseDateV2(DateUtil.format(new Date(), "HH:mm"), "HH:mm");
                int curMinute = DateUtil.getMinute(Objects.requireNonNull(timeEndDate), timeCurrDate);
                int apmMinute = DateUtil.getMinute(timeEndDate, timeStartDate);
                double minute = BigDecimalUtil.divide(curMinute, apmMinute);
                double remainCount = BigDecimalUtil.subtract(maxLimit, apmRecycle);
                currentRemainCount = BigDecimalUtil.round(BigDecimalUtil.multiply(minute, remainCount), 0, 3);
            }
        }
        return currentRemainCount;
    }


    public Map<String, Object> scheduleLimit3(ExamApplyDto ea) {
        Map<String, Object> map = new HashMap<>();

        if (!ConstantsUtil.TerminalType.SELF.getType().equals(ea.getTerminalType())
                && !ConstantsUtil.TerminalType.MOBILE.getType().equals(ea.getTerminalType())) {
            return null;
        }

        int scheCancel = 0;

        for (ExamApplyItem eai : ea.getItems()) {
            int sche = (eai.getScheCancel() == null) ? 0 : eai.getScheCancel();
            if (sche > scheCancel) {
                scheCancel = sche;
            }
        }

        List<ConfigDto.ScheduleLimit> scheduleLimitList = new ArrayList<>();
        String scheduleLimit = getConfigByName(ConstantsUtil.ConfigName.SCHEDULE_LIMIT_BY_TERMINAL.getKey());
        if (StringUtils.isNotBlank(scheduleLimit)) {
            scheduleLimitList = JsonUtil.toList(scheduleLimit, ConfigDto.ScheduleLimit.class);
            if (scheduleLimitList != null && scheduleLimitList.size() > 0) {
                for (ConfigDto.ScheduleLimit list : scheduleLimitList) {
                    if (list.getExamClass().contains(ea.getExamClass())) {

                        // String reminder = customReminder(ConstantsUtil.ConfigName.SCHEDULE_LIMIT_BY_TERMINAL_REMINDER.getKey(), ea);
                        String reminder = "";
                        if (StringUtils.isBlank(reminder)) {
                            reminder = "如有疑问请到科室前台修改或咨询";
                        }
                        scheCancel--;
                        String scheCancelReminder = "";
                        boolean isScheCancel = (scheCancel >= list.getLimitCount());
                        if (isScheCancel) {
                            scheCancelReminder = "该项目自助改约次数已满[已改" + list.getLimitCount() + "次] " + reminder;
                        } else if (scheCancel > 0) {
                            scheCancelReminder = "该项目自助改约限制" + list.getLimitCount() + "次[已改" + scheCancel + "次]。";
                        } else if (StringUtils.isNotBlank(ea.getScheduleStatus()) && !"01".equals(ea.getScheduleStatus())) {

                            scheCancelReminder = "该项目自助改约限制仅" + list.getLimitCount() + "次改约";
                        }
                        map.put("isScheCancel", isScheCancel);
                        map.put("scheCancelReminder", scheCancelReminder);
                        return map;
                    }
                }
            }
        }
        return null;
    }

    /**
     * 获取系统登录配置
     *
     * @return
     */
    public ConfigDto.SystemLoginConfig getSystemLoginConfig() {
        ConfigDto.SystemLoginConfig systemLoginConfig = null;
        String config = getConfigByName(ConstantsUtil.ConfigName.LOGIN_CONFIG.getKey());
        if (StringUtils.isNotBlank(config)) {
            systemLoginConfig = JsonUtil.toBean(config, ConfigDto.SystemLoginConfig.class);
        }
        return systemLoginConfig;
    }

}
